package com.liik.bomb.screen.action;

import com.liik.game.mvc.tiled.object.Entity;
import com.liik.game.mvc.tiled.object.Tile;
import com.liik.game.mvc.tiled.object.Tile.Type;
import com.liik.game.mvc.tiled.TiledGameModel;
import com.liik.game.mvc.tiled.TiledGameModel.Environment;
import com.liik.game.util.Vector;

public class BombEntity extends Entity {
	
	public int rangeNorth;
	public int rangeEast;
	public int rangeSouth;
	public int rangeWest;
	
	public static enum State {
		Counting, Exploding, Done
	}

	public State state;
	public long timestamp;
	public int range;
	public int timer;
	public int explosion;

	public BombEntity() {
		super(.5f, 10);
		state = State.Done;
	}

	@Override
	public boolean isActive() {
		return state != State.Done;
	}

	@Override
	public void update(TiledGameModel gameModel, long currentTimeMillis) {
		switch (state) {
		case Counting:
			if (currentTimeMillis > timestamp) {
				explode(gameModel, currentTimeMillis);
			}
			break;
		case Done:
			break;
		case Exploding:
			if (currentTimeMillis > timestamp) {
				finishExplosion(currentTimeMillis);
			} else {
				burnEnvironment(gameModel);				
			}
			break;
		}
	}

	public void activate(Vector position, int range, int timer, int explosion) {
		this.x = (float)Math.floor(position.x) + .5f;
		this.y = (float)Math.floor(position.y) + .5f;
		this.state = State.Counting;
		this.timestamp = System.currentTimeMillis() + timer;
		this.range = range;
		this.timer = timer;
		this.explosion = explosion;
	}

	private void explode(TiledGameModel gameModel, long currentTimeMillis) {
		if (state == State.Exploding)
			return;
		state = State.Exploding;
		timestamp = currentTimeMillis + explosion;
		explodeTiles(gameModel);
	}
	
	private void finishExplosion(long currentTimeMillis) {
		state = State.Done;
		timestamp = currentTimeMillis;
	}

	private void burnEnvironment(TiledGameModel gameModel) {
		Environment[][] environment = gameModel.getEnvironment();
		int minX = ((int)Math.floor(x)) - rangeWest;
		int maxX = ((int)Math.floor(x)) + rangeEast;
		int x = (int) Math.floor(this.x);
		int minY = ((int)Math.floor(y)) - rangeNorth;
		int maxY = ((int)Math.floor(y)) + rangeSouth;
		int y = (int) Math.floor(this.y);
		for (int i = minX; i <= maxX; ++i) {
			environment[i][y] = Environment.Fire;
		}
		for (int j = minY; j <= maxY; ++j) {
			environment[x][j] = Environment.Fire;
		}
	}

	private void explodeTiles(TiledGameModel gameModel) {
		rangeWest = 0;
		for (int i = (int) Math.floor(x) - 1; i >= x - range - 1; i--) {
			int exploded = explodeTile(gameModel.getTile(i, y));
			if (exploded == 2) {
				break;
			} else if (exploded == 1) {
				rangeWest++;
				break;
			} else {
				rangeWest++;				
			}
		}
		
		rangeEast = 0;
		for (int i = (int) Math.floor(x) + 1; i <= x + range; i++) {
			int exploded = explodeTile(gameModel.getTile(i, y));
			if (exploded == 2) {
				break;
			} else if (exploded == 1) {
				rangeEast++;
				break;
			} else {
				rangeEast++;				
			}
		}
		
		rangeNorth = 0;
		for (int j = (int) Math.floor(y) - 1; j >= y - range - 1; j--) {
			int exploded = explodeTile(gameModel.getTile(x, j));
			if (exploded == 2) {
				break;
			} else if (exploded == 1) {
				rangeNorth++;
				break;
			} else {
				rangeNorth++;				
			}
		}
		
		rangeSouth = 0;
		for (int j = (int) Math.floor(y) + 1; j <= y + range; j++) {
			int exploded = explodeTile(gameModel.getTile(x, j));
			if (exploded == 2) {
				break;
			} else if (exploded == 1) {
				rangeSouth++;
				break;
			} else {
				rangeSouth++;				
			}
		}
	}

	private int explodeTile(Tile tile) {
		if (tile == null)
			return 2;
		switch (tile.type) {
		case Bridge:
			tile.type = Type.Water;
			return 1;
		case Earth:
			tile.type = Type.Empty;
			return 1;
		case Empty:
			return 0;
		case Wall:
			return 2;
		case Water:
			return 1;
		}
		return 2;
	}

	@Override
	public void handleCollision(Entity otherEntity, TiledGameModel gameModel, long currentTimeMillis) {
		// do nothing
	}

	@Override
	public void handleEnvironment(Environment environment, TiledGameModel gameModel, long currentTimeMillis) {
		switch(environment) {
		case Air:
			break;
		case Fire:
			explode(gameModel, currentTimeMillis);
			break;
		case Water:
			break;
		}
	}

	@Override
	public void handleDefaultAction(TiledGameModel gameModel, long currentTimeMillis) {
		// TODO Auto-generated method stub
		
	}
}
